#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2022/3/4 4:06 下午
# @Author  : WangZhixing

# 对bash中的文件中的注释进行提取，并统计
import csv
import json
import re

import os


class c_analyze:
    def __init__(self, root, edge_path=None, symbol_path=None):
        self.count = 0
        self.filename = []
        self.file_property = []
        self.includeset = []
        self.root = root
        # self.edge_path = edge_path
        # self.symbol_path = symbol_path
        self._getfilesname()
        self._get_property()

    def dic2csv(self, path):
        # with open(path, 'w', newline='') as csvfile:  # python3下
        #     writer = csv.writer(csvfile, delimiter=',')
        #     keys = ['id',
        #             'label',
        #             'menuwithname',
        #             'name',
        #             'size',
        #             'lines',
        #             'category',
        #             'type',
        #             'layer',
        #             'conmment',
        #             'include_list',
        #             "in_node",
        #             "in_degreen",
        #             "out_node",
        #             "out_degreen",
        #             "two_hop",
        #             "symbol",
        #             "num_of_symbol"]
        #     i = 1
        #     writer.writerow(keys)
        #     for line in self.file_property:
        #         writer.writerow([str(i),
        #                          line['label'],
        #                          line['menu_name'],
        #                          line['name'],
        #                          line['size'],
        #                          line['lines'],
        #                          line['menu'],
        #                          line['type'],
        #                          line['layer'],
        #                          line['conmment'],
        #                          line['include_list'],
        #                          line['inedge'],
        #                          line["in_degreen"],
        #                          line['outedge'],
        #                          line['out_degreen'],
        #                          line['two_hop'],
        #                          line['symbol'],
        #                          line['num_of_symbol']])
        #         i += 1

        with open(path.replace(".csv", "test.csv"), 'w', newline='') as csvfile:  # python3下
            writer = csv.writer(csvfile, delimiter=',')
            keys = ['id',
                    'label',
                    'menuwithname',
                    ]
            keys += self.includeset
            i = 1
            writer.writerow(keys)
            for line in self.file_property:
                value = []
                value.append(str(i))
                value.append(line['label'])
                value.append(line['menu_name'])
                for includesetfile in self.includeset:
                    if includesetfile in line['include_list']:
                        value.append(1)
                    else:
                        value.append(0)
                writer.writerow(value)
                i += 1

    def _getfilesname(self, path=None):
        if path == None:
            path = self.root
        for filename in os.listdir(path):
            if not filename.startswith("."):
                filepath = os.path.join(path, filename)
                if os.path.isdir(filepath):
                    self._getfilesname(filepath)
                else:
                    self.filename.append(os.path.relpath(filepath, self.root))

    def edge(self):
        in_edge = {}
        out_edge = {}
        with open(self.edge_path, "r") as edgefile:
            for line in edgefile.readlines():
                line = line.split("\n")[0]
                innode = line.split(" ")[1]
                outnode = line.split(" ")[2]
                if innode != outnode:
                    if innode in in_edge:
                        in_edge[innode].append(outnode)
                    else:
                        list = []
                        list.append(outnode)
                        in_edge[innode] = list

                    if outnode in out_edge:
                        out_edge[outnode].append(innode)
                    else:
                        list = []
                        list.append(innode)
                        out_edge[outnode] = list
        return in_edge, out_edge

    def get_property(self):
        return self.file_property

    def _get_property(self):
        for file in self.filename:
            file_dict = {}
            menu, menu_name = self._get_menu_and_menuwithname(file)
            type = self.get_type(file)
            layer = self.layer(file)
            conmment = self.conmment(file)
            include_list = self.includelist(file)
            getnameonly = self.getnameonly(file)
            # inedge, outedge = self.edge()
            size = self.get_size(file)
            lines = self._get_line(file)

            # symbol_dic = self.get_symbol(self.symbol_path)

            file_dict['menu_name'] = menu_name
            file_dict['label'] = file.split("/")[0]
            file_dict['menu'] = menu
            file_dict['size'] = size
            file_dict['lines'] = lines
            file_dict['name'] = getnameonly
            file_dict['include_list'] = include_list
            file_dict['conmment'] = conmment
            file_dict['layer'] = layer
            file_dict['type'] = type
            '''
            in
            
            if menu_name not in inedge:
                file_dict['inedge'] = None
                file_dict['in_degreen'] = 0
            else:
                file_dict['inedge'] = inedge[menu_name]
                file_dict['in_degreen'] = len(inedge[menu_name])
            
            out
            
            if menu_name not in outedge:
                file_dict['outedge'] = None
                file_dict['out_degreen'] = 0
                file_dict['two_hop'] = None

            else:
                file_dict['outedge'] = outedge[menu_name]
                file_dict['out_degreen'] = len(outedge[menu_name])
                two_out_list = []
                for node in outedge[menu_name]:
                    if node in outedge:
                        for out2node in outedge[node]:
                            if out2node != menu_name:
                                two_out_list.append(out2node)

                file_dict['two_hop'] = two_out_list

            
            symbol    
            
            if menu_name not in symbol_dic:
                file_dict['symbol'] = None
                file_dict['num_of_symbol'] = 0
            else:
                file_dict['symbol'] = symbol_dic[menu_name]
                file_dict['num_of_symbol'] = len(symbol_dic[menu_name])
            
            two-hop
            
            self.file_property.append(file_dict)
            '''

    def _get_menu_and_menuwithname(self, file: str) -> str:
        menu_part = file.split("/")
        lenth = len(menu_part)
        path = ""
        for i in range(lenth - 2):
            path = os.path.join(path, menu_part[i + 1])
        path1 = os.path.join(path, menu_part[-1])
        return path, path1

    def layer(self, file: str) -> int:
        return len(file.split("/")) - 2

    # 大小单位 1.00K
    def get_size(self, file):
        filepath = os.path.join(self.root, file)
        fsize = os.path.getsize(filepath)
        fsize = fsize / float(1024)
        return round(fsize, 2)

    def _get_line(self, file):
        filepath = os.path.join(self.root, file)
        count = 0
        for count, line in enumerate(open(filepath, 'rU')):
            count += 1
        return count

    def conmment(self, file: str) -> list:
        filepath = os.path.join(self.root, file)
        with open(filepath, "r") as fp:
            pattern = re.compile(r"/\*[\s\S\r\n]*?\*/", re.I)
            content = fp.read()
            file_comments = pattern.findall(content)

            for i in range(0, len(file_comments)):
                file_comments[i] = file_comments[i].replace("\n\n\n\n\n\n", "\n")
                file_comments[i] = file_comments[i].replace("\n\n\n\n\n", "\n")
                file_comments[i] = file_comments[i].replace("\n\n\n\n", "\n")
                file_comments[i] = file_comments[i].replace("\n\n\n", "\n")
                file_comments[i] = file_comments[i].replace("\n\n", "\n")
                file_comments[i] = file_comments[i].replace("\n", ".")
                file_comments[i] = file_comments[i].replace("\t", ".")
                file_comments[i] = file_comments[i].replace("/*", "")
                file_comments[i] = file_comments[i].replace("*/", "")
                file_comments[i] = file_comments[i].replace("*", "")
            return file_comments

    def get_type(self, file):
        return file.split(".")[-1]

    def includelist(self, file) -> list:
        ret=[]
        filepath = os.path.join(self.root, file)
        with open(filepath, "r") as fp:
            pattern = re.compile(r'\#[ ]*include[ \s]*(<([^"<>|\b]+)>|"([^"<>|\b]+)")', re.I)
            content = fp.read()
            includelist = pattern.findall(content)

            return ret

    def getnameonly(self, file: str):
        return file.split("/")[-1].split(".")[0]

    def get_symbol(self, path):
        new_jsondata = {}
        fp = open(path, "r")
        dic_list = json.load(fp)
        for jsondata in dic_list:
            new_jsondata[jsondata['name']] = jsondata['symbol']
        fp.close()
        return new_jsondata


if __name__ == '__main__':
    c = c_analyze("/Users/wzx/Downloads/module-reverse-by-gnn/Source/bash4.2"
                  # , "/Users/wzx/Downloads/module-reverse-by-gnn/Source/bash_sym_dep.rsf",
                  # "/Users/wzx/Downloads/module-reverse-by-gnn/Source/filedefsymbol.json"
                  )
    li = c.get_property()

    c.dic2csv("/Users/wzx/Downloads/module-reverse-by-gnn/Source/t.csv")
    print(li)
